﻿using System;
using System.Windows;
using System.Windows.Media;
using Microsoft.CSharp.RuntimeBinder;

namespace Leow.SelectableCanvas
{
    internal static class CustomExtensionMethods
    {
        public static void EnsureElementHasHeight(this FrameworkElement element)
        {
            if (element.Height.Equals(double.NaN))
            {
                element.Height = element.ActualHeight;
            }
        }

        public static void EnsureElementHasSize(this FrameworkElement element)
        {
            element
                .EnsureElementHasWidth();
            element
                .EnsureElementHasHeight();
        }

        public static void EnsureElementHasWidth(this FrameworkElement element)
        {
            if (element.Width.Equals(double.NaN))
            {
                element.Width = element.ActualWidth;
            }
        }

        public static double GetActualMinHeight(this FrameworkElement element)
        {
            double actualMinHeight;
            try
            {
                dynamic d = element;
                actualMinHeight = Math.Max(
                    element.MinHeight,
                    d.Padding.Top + d.Padding.Bottom);
            }
            catch (RuntimeBinderException)
            {
                actualMinHeight = element.MinHeight;
            }

            return actualMinHeight;
        }

        public static double GetActualMinWidth(this FrameworkElement element)
        {
            double actualMinWidth;
            try
            {
                dynamic d = element;
                actualMinWidth = Math.Max(
                    element.MinWidth,
                    d.Padding.Left + d.Padding.Right);
            }
            catch (RuntimeBinderException)
            {
                actualMinWidth = element.MinWidth;
            }

            return actualMinWidth;
        }

        /// <summary>
        /// Gets the first parent UI element of a specified source UI element
        /// that matches the specified UI element type. This parent UI element
        /// is located by traversing the visual tree.
        /// </summary>
        /// <typeparam name="T">The type of parent UI element expected.
        /// </typeparam>
        /// <param name="source">A UI element in which to look for the parent UI
        /// element.</param>
        /// <returns>The first parent UI element of the source that is of type
        /// T, or <c>null</c> if there are no such parent UI element.</returns>
        public static T GetFirstVisualParentOfType<T>(this DependencyObject source)
            where T : DependencyObject
        {
            if (source == null)
            {
                return null;
            }

            DependencyObject parent = VisualTreeHelper.GetParent(source);
            if (parent is T)
            {
                return parent as T;
            }

            return parent
                .GetFirstVisualParentOfType<T>();
        }
    }
}
